import { ReactiveProperty } from './../libs/rxjs/cc3/ReactiveProperty';
import { BaseManager } from './../libs/rxjs/cc3/BaseManager';
import { _decorator, color, director, System } from 'cc';
import { fromFetch } from '../libs/rxjs/internal/observable/dom/fetch';
import { throwError, Observable, catchError, lastValueFrom } from 'rxjs';
const { ccclass, property } = _decorator;

const CloudConfig = {
    url: 'http://www.bmma.top:13010/api'
    // url: 'http://localhost:13010/api'
}

@ccclass('CloudManager')
class CloudManager extends BaseManager {
    public static instance: CloudManager;
    static ID = 'cloud_system';
    get logColorOverride() { return color().fromHEX('#CCEEDD') };

    checkPassed = ReactiveProperty.Create(false);

    static registerSystem() {
        director.unregisterSystem(director.getSystem(CloudManager.ID));
        director.registerSystem(CloudManager.ID, cm, System.Priority.MEDIUM);
        cm.init();
    }

    onInitManager() {
        this.log('onInitManager', this.timestamp);
        this.checkCloud();
    }

    /**
     * 获取第一关，来测试网络连通性
     */
    async checkCloud() {
        try {
            await lastValueFrom(this.setStage(0, { hi: 100 }));
            await lastValueFrom(this.getStage(0));
        } catch (err) {
            this.warn('checkCloud', err);
        }
    }

    getStage(stageNumber: number) {
        return new Observable(observer => {
            fromFetch(`${CloudConfig.url}/get/${stageNumber}`, {
                selector: response => {
                    if (response.ok) {
                        return response.json();
                    } else {
                        return throwError(() => new Error(`Error: ${response.status}`));
                    }
                }
            }).subscribe({
                next: _ => {
                    this.log('getStage:', _);
                    this.checkPassed.value = true;
                    observer.next(_.stage);
                    observer.complete();
                },
                error: err => {
                    this.warn('getStage:', err);
                    this.checkPassed.value = false;
                    observer.error(err);
                }
            });
        })
    }

    setStage(stageNumber: number, data: object) {
        return new Observable(observer => {
            fromFetch(`${CloudConfig.url}/set`, {
                method: 'POST',
                body: JSON.stringify({ stageNum: stageNumber, data }),
                headers: {
                    'Content-Type': 'application/json'
                },
                selector: response => {
                    if (response.ok) {
                        return response.json();
                    } else {
                        return throwError(() => new Error(`Error: ${response.status}, ${response.statusText}`));
                    }
                }
            }).subscribe({
                next: _ => {
                    this.log('setStage:', _);
                    this.checkPassed.value = true;
                    observer.next(_.stage);
                    observer.complete();
                },
                error: err => {
                    this.warn('setStage:', err);
                    this.checkPassed.value = false;
                    observer.error(err);
                }
            });
        })
    }
}

globalThis.CloudManager = CloudManager;

export const cm = CloudManager.instance = new CloudManager();


